package com.jxpanda.spring.module.common.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.jxpanda.infrastructure.model.web.Response;
import com.jxpanda.spring.module.common.ResponseWrapper;
import com.jxpanda.spring.module.common.config.properties.GlobalExceptionHandlerProperties;
import com.jxpanda.spring.module.common.config.properties.ResponseWrapperProperties;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.ReactiveAdapterRegistry;
import org.springframework.http.ResponseEntity;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.http.codec.json.Jackson2JsonDecoder;
import org.springframework.http.codec.json.Jackson2JsonEncoder;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.reactive.accept.RequestedContentTypeResolver;
import org.springframework.web.reactive.config.WebFluxConfigurer;
import org.springframework.web.reactive.result.method.annotation.ResponseBodyResultHandler;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Configuration
@RequiredArgsConstructor
@AutoConfigureAfter(JacksonConfigure.class)
public class ResponseWrapperConfigure implements WebFluxConfigurer {

    private final ResponseWrapperProperties responseWrapperProperties;

    private final ObjectMapper objectMapper;

    @Override
    public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {
        configurer.customCodecs().register(new Jackson2JsonEncoder(objectMapper));
        configurer.customCodecs().register(new Jackson2JsonDecoder(objectMapper));
    }

    @Bean
    @Primary
    @ConditionalOnProperty(prefix = "panda.spring.common.response-wrapper", name = "enable", havingValue = "true", matchIfMissing = true)
    public ResponseBodyResultHandler responseBodyResultHandler(@Qualifier("webFluxAdapterRegistry") ReactiveAdapterRegistry reactiveAdapterRegistry,
                                                               ServerCodecConfigurer serverCodecConfigurer,
                                                               @Qualifier("webFluxContentTypeResolver") RequestedContentTypeResolver requestedContentTypeResolver) {
        return new ResponseWrapper(serverCodecConfigurer.getWriters(), requestedContentTypeResolver, reactiveAdapterRegistry, responseWrapperProperties);
    }

    @Slf4j
    @ControllerAdvice
    @RequiredArgsConstructor
    @ConditionalOnProperty(prefix = "panda.spring.common.global-exception-handler", name = "enable", havingValue = "true", matchIfMissing = true)
    public static class GlobalExceptionHandler {

        private final GlobalExceptionHandlerProperties globalExceptionHandlerProperties;

        @ExceptionHandler(Exception.class)
        public Mono<ResponseEntity<Object>> handleException(Exception ex, ServerWebExchange exchange) {
            // 你可以在这里设置不同的响应码（比如 400 或 500）
            ResponseEntity<Object> responseEntity = new ResponseEntity<>(Response.error(ex.getMessage()), globalExceptionHandlerProperties.getHttpStatus());
            return Mono.just(responseEntity)
                    .doFinally(signalType -> log.error("全局异常捕获：{}", ex.getMessage(), ex));
        }
    }


}
